gint position);
-/* CellInfo/CellGroup metadata handling */
+/* CellInfo/CellGroup metadata handling and convenience functions */
typedef struct {
GtkCellRenderer *renderer;
typedef struct {
GList *cells;
- guint id : 16;
+ guint id : 16;
guint expand : 1;
} CellGroup;
static GList *construct_cell_groups (GtkCellAreaBox *box);
static gint count_expand_groups (GtkCellAreaBox *box);
static gint count_expand_cells (CellGroup *group);
-
+static void iter_weak_notify (GtkCellAreaBox *box,
+ GtkCellAreaIter *dead_iter);
+static void flush_iters (GtkCellAreaBox *box);
struct _GtkCellAreaBoxPrivate
{
- GtkOrientation orientation;
+ GtkOrientation orientation;
+
+ GList *cells;
+ GList *groups;
- GList *cells;
- GList *groups;
+ GSList *iters;
- gint spacing;
+ gint spacing;
};
enum {
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
priv->cells = NULL;
priv->groups = NULL;
+ priv->iters = NULL;
priv->spacing = 0;
}
/*************************************************************
- * CellInfo/CellGroup Basics *
+ * CellInfo/CellGroup basics and convenience functions *
*************************************************************/
static CellInfo *
cell_info_new (GtkCellRenderer *renderer,
return expand_cells;
}
+static void
+iter_weak_notify (GtkCellAreaBox *box,
+ GtkCellAreaIter *dead_iter)
+{
+ GtkCellAreaBoxPrivate *priv = box->priv;
+
+ priv->iters = g_slist_remove (priv->iters, dead_iter);
+}
+
+static void
+flush_iters (GtkCellAreaBox *box)
+{
+ GtkCellAreaBoxPrivate *priv = box->priv;
+ GSList *l;
+
+ /* When the box layout changes, iters need to
+ * be flushed and sizes for the box get requested again
+ */
+ for (l = priv->iters; l; l = l->next)
+ {
+ GtkCellAreaIter *iter = l->data;
+
+ gtk_cell_area_iter_flush (iter);
+ }
+}
/*************************************************************
* GObjectClass *
static void
gtk_cell_area_box_finalize (GObject *object)
{
+ GtkCellAreaBox *box = GTK_CELL_AREA_BOX (object);
+ GtkCellAreaBoxPrivate *priv = box->priv;
+ GSList *l;
+
+ for (l = priv->iters; l; l = l->next)
+ g_object_weak_unref (G_OBJECT (l->data), (GWeakNotify)iter_weak_notify, box);
+
+ g_slist_free (priv->iters);
+
G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
}
priv->cells = g_list_delete_link (priv->cells, node);
- /* Reconstruct cell groups
- * XXX TODO: add a list of iters and weak_ref's on them, then
- * flush the iters when we reconstruct groups, change spacing
- * or child expand properties (i.e. notify size needs to be
- * recalculated).
- */
+ /* Reconstruct cell groups */
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
+
+ /* Notify that size needs to be requested again */
+ flush_iters (box);
}
else
g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
static GtkCellAreaIter *
gtk_cell_area_box_create_iter (GtkCellArea *area)
{
- return (GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
+ GtkCellAreaBox *box = GTK_CELL_AREA_BOX (area);
+ GtkCellAreaBoxPrivate *priv = box->priv;
+ GtkCellAreaIter *iter =
+ (GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
+
+ priv->iters = g_slist_prepend (priv->iters, iter);
+
+ g_object_weak_ref (G_OBJECT (iter), (GWeakNotify)iter_weak_notify, box);
+
+ return iter;
}
static GtkSizeRequestMode
priv->cells = g_list_delete_link (priv->cells, node);
priv->cells = g_list_insert (priv->cells, info, position);
+
+ /* Reconstruct cell groups */
+ g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
+ g_list_free (priv->groups);
+ priv->groups = construct_cell_groups (box);
+
+ /* Notify that size needs to be requested again */
+ flush_iters (box);
}
}
priv->cells = g_list_append (priv->cells, info);
- /* Reconstruct cell groups (TODO, notify created iters that size needs renegotiation) */
+ /* Reconstruct cell groups */
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
+
+ /* Notify that size needs to be requested again */
+ flush_iters (box);
}
void
priv->cells = g_list_append (priv->cells, info);
- /* Reconstruct cell groups (TODO, notify created iters that size needs renegotiation) */
+ /* Reconstruct cell groups */
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
+
+ /* Notify that size needs to be requested again */
+ flush_iters (box);
}
gint
{
priv->spacing = spacing;
- /* TODO, notify created iters that size needs renegotiation */
g_object_notify (G_OBJECT (box), "spacing");
+
+ /* Notify that size needs to be requested again */
+ flush_iters (box);
}
}
g_object_thaw_notify (G_OBJECT (iter));
}
+static void
+notify_invalid_height (gpointer width_ptr,
+ CachedSize *size,
+ GtkCellAreaIter *iter)
+{
+ gint width = GPOINTER_TO_INT (width_ptr);
+
+ /* Notify size invalidated */
+ g_signal_emit (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED],
+ 0, width, -1, -1);
+}
+
static void
gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter,
gint width)
/* Flush all sizes for special -1 value */
if (width < 0)
- g_hash_table_remove_all (priv->heights);
+ {
+ g_hash_table_foreach (priv->heights, (GHFunc)notify_invalid_height, iter);
+ g_hash_table_remove_all (priv->heights);
+ }
else
- g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
+ {
+ g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
- /* XXX Should we bother signalling removed values as "size-changed" signals ? */
+ /* Notify size invalidated */
+ g_signal_emit (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED],
+ 0, width, -1, -1);
+ }
}
static void
g_object_thaw_notify (G_OBJECT (iter));
}
+static void
+notify_invalid_width (gpointer height_ptr,
+ CachedSize *size,
+ GtkCellAreaIter *iter)
+{
+ gint height = GPOINTER_TO_INT (height_ptr);
+
+ /* Notify size invalidated */
+ g_signal_emit (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED],
+ 0, height, -1, -1);
+}
+
static void
gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter,
gint height)
/* Flush all sizes for special -1 value */
if (height < 0)
- g_hash_table_remove_all (priv->widths);
+ {
+ g_hash_table_foreach (priv->widths, (GHFunc)notify_invalid_width, iter);
+ g_hash_table_remove_all (priv->widths);
+ }
else
- g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
+ {
+ g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
- /* XXX Should we bother signalling removed values as "size-changed" signals ? */
+ /* Notify size invalidated */
+ g_signal_emit (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED],
+ 0, height, -1, -1);
+ }
}
/*************************************************************